<script setup lang="ts">
import { computed, inject, onActivated, onBeforeUnmount, onDeactivated, onMounted, ref, watch } from 'vue'
import { fabric } from 'fabric'
import _, { throttle } from 'lodash'
import { EnumAllViewType, EnumImgOpType } from '@renderer/views/imgViewer/imgTypes'
import { useActiveOp } from '@renderer/views/imgViewer/hooks/useActiveOp'

const {
  activeOp
} = useActiveOp()
const {
  sendMsg
} = inject('pyImgHandlerIo') as any
const props = defineProps({
  viewType: {
    type: String,
    default: ''
  },
  center: {
    type: Object,
    default: () => {
      return {
        position: [0, 0],
        color: {
          h_color: '',
          v_color: ''
        },
        mip: {
          delta_x: 0,
          delta_y: 0
        }
      }
    }
  }
})

const canvasRef = ref<any>(null)
const radius = 5
const lineStrokeWidth = 0.5
const isDraggingRef = ref(false)
const centerPointRef = computed(() => {
  return {
    x: props.center.position[0],
    y: props.center.position[1]
  }
})

const mipRef = computed(() => {
  return {
    delta_x: props.center.mip.delta_x,
    delta_y: props.center.mip.delta_y
  }
})

onMounted(() => {
  watchResize()
})

onBeforeUnmount(() => {
  resizeObserver.disconnect()
})

const startRender = () => {
  const { width, height } = canvasRef.value.getBoundingClientRect()
  if (width === 0 && height === 0) {
    console.error('crossLayer size 0')
  }
  const hColor = `${props.center.color.h_color}`
  const vColor = `${props.center.color.v_color}`
  canvasRef.value.width = width
  canvasRef.value.height = height

  const canvas = new fabric.Canvas(canvasRef.value, {})
  canvas.selection = false
  let horizontalLine1: fabric.Line
  let horizontalLine2: fabric.Line
  let verticalLine1: fabric.Line
  let verticalLine2: fabric.Line
  let circle: fabric.Circle

  let upMipHorizontalLine: fabric.Line
  let downMipHorizontalLine: fabric.Line
  let leftMipVerticalLine: fabric.Line
  let rightMipVerticalLine: fabric.Line

  watch(centerPointRef, (newVal) => {
    if (!isDraggingRef.value) {
      updateLines(newVal.x, newVal.y)
      updateCircles()
      render()
    }
  })

  watch(mipRef, () => {
    // 如果, mip投影的delta_x /y 都为0 或者 用户正在拖动当前的视图。则不更新。
    if((mipRef.value.delta_x  === 0 && mipRef.value.delta_y  === 0) || isDraggingRef.value) {
      return
    }
    updateMipLines()
    render()
  })

  const render = () => {

    if (mipRef.value.delta_x === 0 && leftMipVerticalLine !== null && rightMipVerticalLine !== null) {
      leftMipVerticalLine.set('visible',false)
      rightMipVerticalLine.set('visible',false)
    }else if (leftMipVerticalLine !== null && rightMipVerticalLine !== null){
      leftMipVerticalLine.set('visible',true)
      rightMipVerticalLine.set('visible',true)
    }
    if (mipRef.value.delta_y === 0 && upMipHorizontalLine !== null && downMipHorizontalLine !== null){
      upMipHorizontalLine.set('visible',false)
      downMipHorizontalLine.set('visible',false)
    }else if (leftMipVerticalLine !== null && downMipHorizontalLine !== null){
      upMipHorizontalLine.set('visible',true)
      downMipHorizontalLine.set('visible',true)
    }

    canvas.renderAll()
  }

  const updateLines = (x = centerPointRef.value.x, y = centerPointRef.value.y) => {
    // 更新线的位置而不是重新创建
    horizontalLine1?.set({
      x1: 0,
      y1: y,
      x2: x - radius,
      y2: y
    })

    horizontalLine2?.set({
      x1: x + radius,
      y1: y,
      x2: canvas.width,
      y2: y
    })

    verticalLine1?.set({
      x1: x,
      y1: 0,
      x2: x,
      y2: y - radius
    })

    verticalLine2?.set({
      x1: x,
      y1: y + radius,
      x2: x,
      y2: canvas.height
    })
  }

  const updateMipLines = (x = centerPointRef.value.x, y = centerPointRef.value.y) => {
    const deltaX = mipRef.value.delta_x
    const deltaY = mipRef.value.delta_y
    const w = canvas.width as number
    const h = canvas.height as number
    leftMipVerticalLine.set({
      x1: x - deltaX,
      y1: 0,
      x2: x - deltaX,
      y2: h
    })
    rightMipVerticalLine.set({
      x1: x + deltaX,
      y1: 0,
      x2: x + deltaX,
      y2: h
    })
    upMipHorizontalLine.set({
      x1: 0,
      y1: y - deltaY,
      x2: w,
      y2: y - deltaY
    })
    downMipHorizontalLine.set({
      x1: 0,
      y1: y + deltaY,
      x2: w,
      y2: y + deltaY
    })
  }

  const updateCircles = () => {
    const { x, y } = centerPointRef.value
    circle.set({
      left: x - radius,
      top: y - radius
    })
    // 更新小球的坐标，以便其可以继续移动。
    circle.setCoords()
  }
  const initLines = () => {
    const { x, y } = centerPointRef.value
    // 初始化线段
    horizontalLine1 = new fabric.Line([0, y, x - radius, y], {
      stroke: hColor,
      strokeWidth: lineStrokeWidth,
      selectable: false,
      hoverCursor: 'default'
    })
    horizontalLine2 = new fabric.Line([x + radius, y, canvas.width, y], {
      stroke: hColor,
      strokeWidth: lineStrokeWidth,
      selectable: false,
      hoverCursor: 'default'
    })

    verticalLine1 = new fabric.Line([x, 0, x, y - radius], {
      stroke: vColor,
      strokeWidth: lineStrokeWidth,
      selectable: false,
      hoverCursor: 'default'
    })

    verticalLine2 = new fabric.Line([x, y + radius, x, canvas.height], {
      stroke: vColor,
      strokeWidth: lineStrokeWidth,
      selectable: false,
      hoverCursor: 'default'
    })

    canvas.add(horizontalLine1, horizontalLine2, verticalLine1, verticalLine2)
  }
  const initMipLines = () => {
    const { x, y } = centerPointRef.value
    const deltaX = mipRef.value.delta_x
    const deltaY = mipRef.value.delta_y
    const w = canvas.width as number
    const h = canvas.height as number
    leftMipVerticalLine = new fabric.Line([x - deltaX, 0, x - deltaX, h], {
      stroke: vColor,
      strokeWidth: lineStrokeWidth,
      selectable: false,
      hoverCursor: 'default',
      strokeDashArray: [3, 3]
    })
    rightMipVerticalLine = new fabric.Line([x + deltaX, 0, x + deltaX, h], {
      stroke: vColor,
      strokeWidth: lineStrokeWidth,
      selectable: false,
      hoverCursor: 'default',
      strokeDashArray: [3, 3]
    })
    canvas.add(leftMipVerticalLine, rightMipVerticalLine)

    upMipHorizontalLine = new fabric.Line([0, y - deltaY, w, y - deltaY], {
      stroke: hColor,
      strokeWidth: lineStrokeWidth,
      selectable: false,
      hoverCursor: 'default',
      strokeDashArray: [3, 3]
    })
    downMipHorizontalLine = new fabric.Line([0, y + deltaY, w, y + deltaY], {
      stroke: hColor,
      strokeWidth: lineStrokeWidth,
      selectable: false,
      hoverCursor: 'default',
      strokeDashArray: [3, 3]
    })
    canvas.add(upMipHorizontalLine, downMipHorizontalLine)
  }

  const initCircle = () => {
    const { x, y } = centerPointRef.value
    circle = new fabric.Circle({
      left: x - radius,
      top: y - radius,
      radius: radius,
      stroke: '',
      strokeWidth: lineStrokeWidth,
      hasControls: false,
      hasBorders: false,
      fill: 'rgba(255, 255, 255, 0)',
      hoverCursor: 'default'
    })
    canvas.add(circle)
  }

  initLines()
  initMipLines()
  initCircle()
  render()

  canvas.on('object:moving', _.throttle(function(e) {
    isDraggingRef.value = true
    const { left, top } = e.target
    if (isDraggingRef.value) {
      updateLines(left + radius, top + radius)
      updateMipLines(left + radius, top + radius)
    }
    const msg = {
      viewType: props.viewType,
      opType: 'move_scroll_absolute',
      x: left + radius,
      y: top + radius
    }
    sendMsg(msg)
  }, 30))

  canvas.on('mouse:up', () => {
    console.log('up clear drag status')
    isDraggingRef.value = false
  })
}

let resizeObserver: ResizeObserver
const watchResize = () => {
  resizeObserver = new ResizeObserver(
    _.debounce((entries) => {
      const { width, height } = entries[0].contentRect
      if (width !== 0 && height !== 0) {
        setTimeout(() => {
          startRender()
        }, 300)
      }
    })
  )
  // 绑定监听的dom
  resizeObserver.observe(canvasRef.value)
}

</script>

<template>
  <div ref="containerRef"
       class="w-full h-full absolute left-0 top-0">
    <canvas ref="canvasRef" class="w-full h-full"></canvas>
  </div>
  <canvas class="w-full h-full z-[10] absolute left-0 top-0" v-if="activeOp.type !== EnumImgOpType.cross"></canvas>
</template>
